package com.archerdu.common.filter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.archerdu.apply.model.Function;
import com.archerdu.apply.model.Menu;
import com.archerdu.apply.model.Role;
import com.archerdu.apply.model.User;
import com.archerdu.apply.service.FunctionManager;
import com.archerdu.apply.service.UserManager;
import com.archerdu.commons.constant.DataConstant;

/**
 * 权限控制
 * 
 * @projectName springDemo
 * @description 权限控制
 * @author archer du
 * @createDate 2013年9月27日 下午5:25:25
 * @updateUser dxf
 * @updateDate 2013年9月27日 下午5:25:25
 * @updateRemark 新建
 * @version 0.0.1
 */
public class RightFilter implements Filter {

    /** 功能列表 */
    public static List<Function> FUNCTION_LIST = null;
    /** 功能列表最近更新时间 */
    public static Long           TIME_STAMP    = System.currentTimeMillis();
    /** 功能列表更新间隔时间 */
    public static Long           INTERVAL      = 20 * 60 * 1000L;

    private Log                  logger        = LogFactory.getLog(getClass());
    private FunctionManager      functionManager;
    private UserManager          userManager;

    @Override
    public void destroy() {

        // Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
            ServletException {

        HttpServletRequest requ = (HttpServletRequest) req;
        HttpServletResponse resp = (HttpServletResponse) res;

        // 初始化并定时更新功能列表
        if (FUNCTION_LIST == null || (System.currentTimeMillis() - TIME_STAMP > INTERVAL)) {
            FUNCTION_LIST = functionManager.getAll();
        }
        String uri = requ.getRequestURI();
        HttpSession session = requ.getSession();
        User user = null;

        // 登录判断，先在程序里写，以后改成可配置
        if ((!uri.startsWith("/admin/login")) && uri.startsWith("/admin")
                && null == session.getAttribute(DataConstant.SESSION_SYS_USER)) {
            resp.sendRedirect("/admin/login.dhtml");
            return;
        } else {
            user = (User) session.getAttribute(DataConstant.SESSION_SYS_USER);
            // 判断资源是否受限
            logger.debug("start check functions");
            for (Function fuc : FUNCTION_LIST) {
                logger.debug("is this url allow to access " + fuc.getUrl() + ": " + uri.startsWith(fuc.getUrl()));
                if (uri.startsWith(fuc.getUrl())) {
                    boolean noright = true;
                    loop: for (Role role : user.getRoles()) {
                        for (Function func : role.getFunctions()) {
                            logger.debug("is the user allowed to access " + func.getUrl().equals(fuc.getUrl()));
                            if (func.getUrl().equals(fuc.getUrl())) {
                                noright = false;
                                break loop;
                            }
                        }
                    }

                    if (noright) {
                        resp.sendRedirect("/admin/noright.dhtml");
                        return;
                    }
                }
            }

        }

        if (uri.startsWith("/examin/questions.dhtml") && null == session.getAttribute(DataConstant.SESSION_COMMON_USER)) {
            resp.sendRedirect("/login.dhtml?returnUrl=" + uri + "?" + requ.getQueryString());
        }

        if ((uri.startsWith("/login.") || uri.startsWith("/register."))
                && null != session.getAttribute(DataConstant.SESSION_COMMON_USER)) {
            resp.sendRedirect("/");
        }
        // 添加目录列表
        addMenus2Session(session, uri);

        chain.doFilter(requ, resp);

    }

    /**
     * 添加目录列表
     * 
     * @param session
     * @param uri
     */
    private void addMenus2Session(HttpSession session, String uri) {
        // 目录列表
        if (null != session.getAttribute(DataConstant.SESSION_SYS_USER)) {
            User user = (User) session.getAttribute(DataConstant.SESSION_SYS_USER);

            List<Menu> menuList = new ArrayList<Menu>();
            List<Menu> subMenuList = new ArrayList<Menu>();

            if (user != null) {
                // 根据uri查找当前子目录
                Integer parentId = null;
                // 存放menu的id值， 防止重复读取menu
                Set<Integer> idSet = new HashSet<Integer>();
                for (Role role : user.getRoles()) {
                    // 判断角色是否正在使用
                    if (role.getUseFlag().equals(DataConstant.COMMON_USE_FLAG_YES)) {
                        for (Menu menu : role.getMenus()) {
                            // 主目录
                            if (menu.getParentId().equals(0) && idSet.add(menu.getId())) {
                                logger.debug("uri.startsWith(menu.getNote()) " + uri.startsWith(menu.getNote()));
                                if (uri.startsWith(menu.getNote())) {
                                    menu.setChecked(DataConstant.COMMON_TRUE);
                                    parentId = menu.getId();
                                } else {
                                    menu.setChecked(DataConstant.COMMON_FALSE);
                                }
                                menuList.add(menu);
                                logger.debug("menu.getChecked() is " + menu.getChecked());
                            }
                            // 取父目录id值
                            if (!menu.getParentId().equals(0) && uri.startsWith(menu.getNote())) {
                                parentId = menu.getParentId();
                            }
                        }
                    }
                }

                if (parentId == null && uri.startsWith("/admin")) {
                    logger.debug(uri + " is not allowed to be visited");
                } else {
                    logger.debug(uri + " is allowed to be visited");
                    // 找出选中的主目录
                    if (null != parentId) {
                        for (Menu menu : menuList) {
                            logger.debug("parentId : menu is " + parentId + " : " + menu);
                            logger.debug("parentId.equals(menu.getId()) " + parentId.equals(menu.getId()));
                            if (parentId.equals(menu.getId())) {
                                menu.setChecked(DataConstant.COMMON_TRUE);
                            }
                        }
                    }
                    for (Role role : user.getRoles()) {
                        for (Menu menu : role.getMenus()) {
                            // 子目录
                            if (menu.getParentId().equals(parentId) && idSet.add(menu.getId())) {
                                if (uri.startsWith(menu.getNote())) {
                                    menu.setChecked(DataConstant.COMMON_TRUE);
                                } else {
                                    menu.setChecked(DataConstant.COMMON_FALSE);
                                }
                                subMenuList.add(menu);
                            }
                        }
                    }
                }
            }
            // 排序
            Collections.sort(menuList);
            Collections.sort(subMenuList);

            session.setAttribute(DataConstant.SESSION_MAIN_MENU_NAME, menuList);
            session.setAttribute(DataConstant.SESSION_SUB_MENU_NAME, subMenuList);
        }
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {

        // Auto-generated method stub

    }

    public FunctionManager getFunctionManager() {

        return functionManager;
    }

    public void setFunctionManager(FunctionManager functionManager) {

        this.functionManager = functionManager;
    }

    public UserManager getUserManager() {
        return userManager;
    }

    public void setUserManager(UserManager userManager) {
        this.userManager = userManager;
    }
}
